﻿using System;
using System.Collections;
using System.Web.Caching;

namespace MvcSupplantCaching
{
    /// <summary>
    /// Base abstract class for a class that inherits OutputCacheProvider and implements IOutputDependencyProvider.
    /// </summary>
    public abstract class BaseOutputCacheProvider : OutputCacheProvider, IOutputDependencyProvider
    {
        /// <summary>
        /// The cache key for the dependencies cache.
        /// </summary>
        public const string CacheDependenciesKey = "Cache-Dependencies";
        public override object Add(string key, object entry, DateTime utcExpiry)
        {
            return AddEntry(key, entry, utcExpiry);
        }

        /// <summary>
        /// Adds an object to the output cache.
        /// </summary>
        /// <param name="key">The cache key to use for the object.</param>
        /// <param name="entry">The new cache entry to be added to the cache.</param>
        /// <param name="utcExpiry">The absolute time the entry expires from the cache.</param>
        /// <returns>The entry that was added to the cache.</returns>
        protected abstract object AddEntry(string key, object entry, DateTime utcExpiry);

        public override object Get(string key)
        {
            return GetEntry(key);
        }

        /// <summary>
        /// Retrieves an object from the cache by a key.
        /// </summary>
        /// <param name="key">The cache key to get the entry for.</param>
        /// <returns>The cached object.</returns>
        protected abstract object GetEntry(string key);

        public override void Remove(string key)
        {
            RemoveEntry(key);
        }

        /// <summary>
        /// Removes an entry from the cache.
        /// </summary>
        /// <param name="key">The cache key to remove the entry for.</param>
        protected abstract void RemoveEntry(string key);

        public override void Set(string key, object entry, DateTime utcExpiry)
        {
            SetEntry(key, entry, utcExpiry);
        }

        /// <summary>
        /// Sets an entry in the cache, creating it if it did not exist before.
        /// </summary>
        /// <param name="key">The cache key to use for the object.</param>
        /// <param name="entry">The entry to be updated or created.</param>
        /// <param name="utcExpiry">The absolute time the entry expires from the cache.</param>
        protected abstract void SetEntry(string key, object entry, DateTime utcExpiry);

        /// <summary>
        /// The IDictionary act as a temporary or request duration cache for items that should be cached short term only.
        /// </summary>
        public IDictionary RequestCache
        {
            get { return ImplementedRequestCache; }
        }

        /// <summary>
        /// Cache to store short-term items such as dependency keys before they are finalized.
        /// This cache should only be good for the duration of a web request or should be cleared 
        /// periodically.
        /// </summary>
        protected abstract IDictionary ImplementedRequestCache { get; }
    }
}
